
#include <BHBoxLayout>
#include <BPainter>
#include <BStyle>
#include <BSpring>
#include <BListItem>
#include <BGridLayout>
#include <BLabel>
#include <BVBoxLayout>
#include <BFileDialog>
#include <BReadWrite>
#include <BColorDialog>

#include "PainterDialog.h"

PainterDialog::PainterDialog(BWidget* parent) : BDialog(parent)
{
	_paintHandler = new PaintHandler();

	_imageButton = new BButton("images");
	_imageButton->setForm(Form_IconOnly);
	_imageButton->setIconSize(100);
	_imageButton->setSizePolicy(Policy_Preferred | Policy_Expanding);

	BGridLayout* gridLayout = new BGridLayout();
	{
		BLabel* sizeLabel = new BLabel("size");
		_brushSizeSlider = new BSlider(0, 300);
		_brushSizeSlider->setGraph(Graph_Circle_Fill);
		_brushSizeSlider->setIconSize(16);
		_brushSizeSpinBox = new BSpinBox(0, 300);
		_brushSizeSpinBox->setSuffix("px");
		BLabel* brushColorLabel = new BLabel("color");
		_brushColorButton = new BButton(Graph_Square_Fill);
		_brushColorButton->setColor(255, 0, 0);

		gridLayout->addWidget(0, 0, sizeLabel);
		gridLayout->addWidget(0, 1, _brushSizeSlider);
		gridLayout->addWidget(0, 2, _brushSizeSpinBox);
		gridLayout->addWidget(1, 0, brushColorLabel);
		gridLayout->addWidget(1, 1, _brushColorButton);
	}

	BHBoxLayout* hlayout = new BHBoxLayout();
	{
		_showPointsCheckBox = new BCheckBox("show points");
		_textureButton = new BButton("Texture");
		_textureButton->setCheckable(true);
		_textureButton->setChecked(true);
		_maskImageButton = new BButton("Mask");
		_maskImageButton->setCheckable(true);
		_maskImageButton->setChecked(true);
		_chessboardButton = new BButton("ChessBoard");
		_chessboardButton->setCheckable(true);
		_chessboardButton->setChecked(true);
		hlayout->addSpring();
		hlayout->addWidget(_showPointsCheckBox);
		hlayout->addWidget(_textureButton);
		hlayout->addWidget(_maskImageButton);
		hlayout->addWidget(_chessboardButton);
	}
	_graphSpacer = new BSpacer();
	_graphSpacer->setMinSize(300);

	BVBoxLayout* vlayout = new BVBoxLayout(this);
	vlayout->addWidget(_imageButton, 0);
	vlayout->addLayout(gridLayout, 0);
	vlayout->addLayout(hlayout, 0);
	vlayout->addSpacer(_graphSpacer);

	connect(_imageButton, Signal_Clicked, &PainterDialog::slotImageButtonClicked);
	connect(_imageButton, Signal_RightClicked, &PainterDialog::slotImageButtonRightClicked);
	connect(_brushSizeSlider, Signal_ValueChanged, &PainterDialog::slotBrushSizeChanged);
	connect(_brushSizeSpinBox, Signal_ValueEdited, &PainterDialog::slotBrushSizeChanged);
	connect(_brushColorButton, Signal_Clicked, &PainterDialog::slotColorButtonClicked);
	connect(_showPointsCheckBox, Signal_Checked, &PainterDialog::slotShowPointChecked);
	connect(_textureButton, Signal_Checked, &PainterDialog::slotTextureButtonChecked);
	connect(_maskImageButton, Signal_Checked, &PainterDialog::slotMaskImageButtonChecked);
	connect(_chessboardButton, Signal_Checked, &PainterDialog::slotChessboardButtonChecked);

	_brushSizeSlider->setValue(200);

}
PainterDialog::~PainterDialog()
{

}

void PainterDialog::setTerrain(BTerrain* terrain)
{
	_terrain = terrain;
	BImage* image = 0;
	if (_terrain)
	{
		image = dynamic_cast<BImage*>(_terrain->texture());
	}
	if (_textureButton->asset() != image)
	{
		if (BImage* oldImage = _textureButton->asset())
		{
			disconnect(oldImage);
		}
		_textureButton->setAsset(image);
		_maskImageButton->setAsset(BValue());
		if (image)
		{
			BImage* chessboard = new BImage(image->size(), Format_Gray);
			BByte* data = chessboard->pixels()->data();
			for (int r = 0; r < chessboard->height(); r++)
			{
				BByte gray = r % 2 ? 255 : 128;
				BByte back = gray == 255 ? 128 : 255;
				int pos = r * chessboard->width();
				for (int c = 0; c < chessboard->width(); c++)
				{
					if (c % 2)
						data[pos + c] = back;
					else
						data[pos + c] = gray;
				}
			}
			chessboard->setFilter(BTexture::Filter_Nearest);
			_chessboardButton->setAsset(chessboard);
			connect(image, Signal_Dirty, &PainterDialog::slotTerrainTextureDirty);
		}
	}
}
BTerrain* PainterDialog::terrain() const
{
	return _terrain;
}

void PainterDialog::slotImageButtonClicked(BObject* object, const BValue& value)
{
	const BString& fileName = BFileDialog::OpenFile("Choose Brush Image", "./data/image");
	if (fileName.size())
	{
		BImage* image = ReadFile<BImage>(fileName);
		_imageButton->setImage(image);
		_paintHandler->setBrushImage(image);
	}
}
void PainterDialog::slotImageButtonRightClicked(BObject* object, const BValue& value)
{
	_imageButton->setImage(0);
	_paintHandler->setBrushImage(0);
}
void PainterDialog::slotBrushSizeChanged(BObject* object, const BValue& value)
{
	if (object == _brushSizeSlider)
	{
		int size = value;
		_paintHandler->setBrushSize(size);
		_brushSizeSpinBox->setValue(size);
	}
	if (object == _brushSizeSpinBox)
	{
		int size = value;
		_paintHandler->setBrushSize(size);
		_brushSizeSlider->setValue(size);
	}
}
void PainterDialog::slotColorButtonClicked(BObject* object, const BValue& value)
{
	BColor color = BColorDialog::ChooseColor("Choose Button Color", _brushColorButton->color());
	_brushColorButton->setColor(color);
	_paintHandler->setBrushColor(color);
}
void PainterDialog::slotShowPointChecked(BObject* object, const BValue& value)
{
	bool pointVisible = value;
	_paintHandler->setPointVisible(pointVisible);
}
void PainterDialog::slotTextureButtonChecked(BObject* object, const BValue& value)
{
	
}
void PainterDialog::slotMaskImageButtonChecked(BObject* object, const BValue& value)
{
	
}
void PainterDialog::slotChessboardButtonChecked(BObject* object, const BValue& value)
{

}
void PainterDialog::slotTerrainTextureDirty(BObject* object, const BValue& value)
{
	this->fresh();
}

void PainterDialog::showEvent(const BEvent& event)
{
	_paintHandler->setBrushSize(_brushSizeSlider->value());
	_paintHandler->setBrushImage(_imageButton->image());
	_paintHandler->setBrushColor(_brushColorButton->color());
	_paintHandler->setPointVisible(_showPointsCheckBox->checked());
	_paintHandler->setAsset(_terrain);
	emit("apply-handler", _paintHandler);
	BDialog::showEvent(event);
}
void PainterDialog::hideEvent(const BEvent& event)
{
	_paintHandler->detach();
	BDialog::hideEvent(event);
}

void PainterDialog::styleEvent(const BEvent& event)
{
	BDialog::styleEvent(event);
}
void PainterDialog::paintEvent(const BEvent& event)
{
	BDialog::paintEvent(event);
	BPainter painter(this);
	if (BImage* image = _textureButton->asset())
	{
		BRect graphRect = _graphSpacer->rect();
		painter.drawImage(graphRect, image);
	}
}
